#ifndef COMMON_LOG_MALWARE_TEAM_H_
#define COMMON_LOG_MALWARE_TEAM_H_

#include "lockEx.h"
#include "ThreadLangLocal.h"

#define GLOBAL_LOG_EVENT_XX		_T("FanTasyliLogEventLock")

class LogItem
{
public:
	LogItem(){}
	~LogItem(){}

public:
	DWORD					nId;
	CString					strTime;
	CString					strLogInfo;
};

class CCommonLog
{
public:
	~CCommonLog()
	{
		FlushLog();
		ReleaseLogLock();
	}

	VOID LogItemToFile(DWORD nItemId, const CString& strLogInfo)
	{
		LogItem* pItem = new LogItem;

		if (pItem)
		{
			CTime timeNow = CTime::GetCurrentTime();

			pItem->nId = nItemId;
			pItem->strLogInfo = strLogInfo;

			pItem->strTime.Format( _T("%04d-%02d-%02d %02d:%02d:%02d"), timeNow.GetYear(), timeNow.GetMonth(), timeNow.GetDay(), 
				timeNow.GetHour(), timeNow.GetMinute(), timeNow.GetSecond());

			m_logList.Add(pItem);
			FlushLog();
		}

	}

	VOID FlushLog(DWORD dwMini = 1)
	{
		CMarkup	mark;
		BOOL	bLoadXmlOK;

		if (m_logList.GetSize() >= (int)dwMini && !m_strLogPath.IsEmpty())
		{
			USE_CHINESE_LANG_LOCAL;
			GetLogLock();

			bLoadXmlOK = mark.Load(m_strLogPath);

			if (bLoadXmlOK)
			{
				if (mark.FindElem(_T("xml")))
				{
					mark.IntoElem();
				}
				else
				{
					mark.InsertElem( _T("xml") );
					mark.IntoElem();
				}
			}
			else
			{
				mark.SetDoc(_T(""));
				mark.InsertElem(_T("xml"));
				mark.IntoElem();
				bLoadXmlOK = TRUE;
			}

			for (INT i = 0; i < m_logList.GetSize(); i++)
			{
				LogItem* logItem = m_logList[i];
				if (bLoadXmlOK)
				{
					mark.AddElem( _T("item") );
					mark.AddAttrib( _T("id"), logItem->nId);
					mark.AddAttrib( _T("time"), logItem->strTime);
					mark.AddAttrib(_T("logInfo"), logItem->strLogInfo);
				}

				delete logItem;
			}

			mark.OutOfElem();

			if (bLoadXmlOK)
			{
				mark.Save(m_strLogPath);
			}

			m_logList.RemoveAll();
			ReleaseLogLock();

		}
	}

	VOID GetLogLock()
	{
		static	CLock	lockx;

		lockx.Lock();

		do 
		{
			m_hLogEvent = ::CreateEvent( NULL, FALSE, FALSE, GLOBAL_LOG_EVENT_XX);
			if ( GetLastError() == ERROR_ALREADY_EXISTS )
			{
				::CloseHandle(m_hLogEvent);
				m_hLogEvent = NULL;
			}
			else if ( m_hLogEvent != NULL )
				break;

			Sleep(10);
		} while ( TRUE );

		lockx.Release();
	}

	VOID ReleaseLogLock()
	{
		if ( m_hLogEvent != NULL )
		{
			::CloseHandle(m_hLogEvent);
			m_hLogEvent = NULL;
		}
	}

	static CCommonLog& GetInstance()
	{
		static CCommonLog s_GlobalLog;
		return s_GlobalLog;
	}

private:
	CString m_strLogPath;
	CSimpleArray<LogItem*> m_logList;
	HANDLE m_hLogEvent;
private:
	CCommonLog() : m_hLogEvent(NULL), m_strLogPath(_T(""))
	{
		m_logList.RemoveAll();
		if (::GetModuleFileName(NULL, m_strLogPath.GetBuffer(MAX_PATH), MAX_PATH) != 0)
		{
			::PathRemoveFileSpec(m_strLogPath.GetBuffer());
			::PathAppend(m_strLogPath.GetBuffer(), _T("debugX.log"));
			m_strLogPath.ReleaseBuffer();
		}
		else

		{
			m_strLogPath.ReleaseBuffer();
			m_strLogPath = _T("c:\\debugX.log");
		}

	}

	CCommonLog(const CCommonLog&);
};


#define LOG_INFO_TO_FILE(XXId, XXStrInfo)	\
	CCommonLog::GetInstance().LogItemToFile(XXId, XXStrInfo);




#endif	// COMMON_LOG_MALWARE_TEAM_H_